#pragma once
#include"Task.hpp"
#include"Cond.hpp"
#include"Lock.hpp"

#include"Log.hpp"
#include"Thread.hpp"

#include<iostream>
#include<pthread.h>
#include<vector>
#include<queue>
#include<memory>
#include<functional>

using namespace LogMoudle;
using namespace LockModule;
using namespace ThreadMoudle;

namespace ThreadPoolMoudle{

    const static int DefaultNumber=5;

    template <typename T>
    //这里的T代指任务类型
    class ThreadPool
    {
    private:
        int _thread_number;
        std::vector<Thread> _threads;
        std::queue<T> _taskqe;

        Cond _condlock;
        Mutex _mutex;

        int wait_number;
        bool isruning;

        //对任务进行的处理
        void Hander_task(std::string name)
        {
            LOG(Logevel::INFO)<<name<<" is Hander_task.....";
            while(true)
            {
                LockGuard lok (_mutex);
                //这里不能用if,不然会陷入死锁问题
                //这里的isruning不能少，不然线程唤醒后就会满足条件，就会再次陷入休眠
                while(_taskqe.empty()&&isruning)
                {
                    wait_number++;
                    //对于条件变量的封装可能有问题
                    _condlock.Wait(_mutex);
                    wait_number--;
                }

                if(_taskqe.empty()&&!isruning)
                {
                    break;
                }

                //获取任务
                T t=_taskqe.front();
                _taskqe.pop();

                //执行任务
                LOG(Logevel::INFO)<<"执行任务";
                t(name);//这里的参数会缺少

            }
        }
    public:

        ThreadPool(int thread_number=DefaultNumber):_thread_number(thread_number),
        wait_number(0),isruning(false)
        {
            LOG(Logevel::INFO)<<"threadpool creat";
        }

        void InintThreadPool()
        {
            for(int num=0;num<_thread_number;num++)
            {
                //建立相应的线程，线程应该绑定hander_task执行方法
                 _threads.emplace_back(std::bind(&ThreadPool<T>::Hander_task,this,std::placeholders::_1));
                 LOG(Logevel::INFO)<<"init thread"<<_threads.back().getName();
               // _threads.emplace_back(std::bind(&ThreadPool<T>::Hander_task, this, "Thread " + std::to_string(num)));
            }
        }

        void Start()
        {
            if(isruning)
            {
                return;
            }
            isruning=true;
            for(auto& a:_threads)
            {
                a.Start();
                LOG(Logevel::INFO)<<a.getName()<<" start ";
            }
        }

        //线程池停止
        //让线程自己退出
        //历史的任务被处理完毕
        void Stop()
        {
            if (isruning)
            {
                isruning = false;
                if(wait_number>0)
                _condlock.NotifyAll();
                LOG(Logevel::INFO) << "线程池退出.....";
            }
        }

        //线程退出
        void Wait()
        {
            LOG(Logevel::INFO)<<"任务执行完毕准备退出....";
            for(auto &a:_threads)
            {
                a.Join();
                LOG(Logevel::INFO)<<a.getName()<<"退出....";
            }
        }

        //加入任务
        bool Enqueue(const T &t)
        {
            bool ret=false;
            LockGuard lok (_mutex);
            if(isruning)
            {
                _taskqe.push(t);
                if(wait_number>0)
                {
                    _condlock.Notify();
                }
                LOG(Logevel::INFO)<<"任务加入队列";
                ret=true;
            }
            return ret;
        }
        
    };
    
    
}